define(["require", "exports", "vscode-languageclient/client", "vscode-languageclient/colorProvider", "vscode-languageclient/configuration", "vscode-languageclient/implementation", "vscode-languageclient/typeDefinition", "vscode-languageclient/workspaceFolders", "vscode-languageclient/utils/is", "vscode-languageclient/configuration", "vscode-languageclient/client"], function (require, exports, client_1, colorProvider_1, configuration_1, implementation_1, typeDefinition_1, workspaceFolders_1, Is, configuration_2, client_2) {
    /* --------------------------------------------------------------------------------------------
     * Copyright (c) Microsoft Corporation. All rights reserved.
     * Licensed under the MIT License. See License.txt in the project root for license information.
     * ------------------------------------------------------------------------------------------ */
    'use strict';
    function __export(m) {
        for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
    }
    Object.defineProperty(exports, "__esModule", { value: true });
    __export(configuration_2);
    __export(client_2);
    var Executable;
    (function (Executable) {
        function is(value) {
            return Is.string(value.command);
        }
        Executable.is = is;
    })(Executable || (Executable = {}));
    var TransportKind;
    (function (TransportKind) {
        TransportKind[TransportKind["stdio"] = 0] = "stdio";
        TransportKind[TransportKind["ipc"] = 1] = "ipc";
        TransportKind[TransportKind["pipe"] = 2] = "pipe";
        TransportKind[TransportKind["socket"] = 3] = "socket";
    })(TransportKind = exports.TransportKind || (exports.TransportKind = {}));
    var Transport;
    (function (Transport) {
        function isSocket(value) {
            let candidate = value;
            return candidate && candidate.kind === TransportKind.socket && Is.number(candidate.port);
        }
        Transport.isSocket = isSocket;
    })(Transport || (Transport = {}));
    var NodeModule;
    (function (NodeModule) {
        function is(value) {
            return Is.string(value.module);
        }
        NodeModule.is = is;
    })(NodeModule || (NodeModule = {}));
    var StreamInfo;
    (function (StreamInfo) {
        function is(value) {
            let candidate = value;
            return candidate && candidate.writer !== void 0 && candidate.reader !== void 0;
        }
        StreamInfo.is = is;
    })(StreamInfo || (StreamInfo = {}));
    //export type ServerOptions = Executable | { run: Executable; debug: Executable; } | { run: NodeModule; debug: NodeModule } | NodeModule | (() => Thenable<ChildProcess | StreamInfo | MessageTransports | ChildProcessInfo>);
    class LanguageClient extends client_1.BaseLanguageClient {
        constructor(arg1, arg2, arg3, arg4, arg5) {
            let id;
            let name;
            let clientOptions;
            let forceDebug;
            if (Is.string(arg2)) {
                id = arg1;
                name = arg2;
                clientOptions = arg4;
                forceDebug = !!arg5;
            }
            else {
                id = arg1.toLowerCase();
                name = arg1;
                clientOptions = arg3;
                forceDebug = arg4;
            }
            if (forceDebug === void 0) {
                forceDebug = false;
            }
            super(id, name, clientOptions);
        }
        // public stop(): Thenable<void> {
        // 	return super.stop().then(() => {
        // 		if (this._serverProcess) {
        // 			let toCheck = this._serverProcess;
        // 			this._serverProcess = undefined;
        // 			if (this._isDetached === void 0 || !this._isDetached) {
        // 				this.checkProcessDied(toCheck);
        // 			}
        // 			this._isDetached = undefined;
        // 		}
        // 	});
        // }
        // private checkProcessDied(childProcess: ChildProcess | undefined): void {
        // 	if (!childProcess) {
        // 		return;
        // 	}
        // 	setTimeout(() => {
        // 		// Test if the process is still alive. Throws an exception if not
        // 		try {
        // 			process.kill(childProcess.pid, <any>0);
        // 			terminate(childProcess);
        // 		} catch (error) {
        // 			// All is fine.
        // 		}
        // 	}, 2000);
        // }
        // protected handleConnectionClosed() {
        // 	this._serverProcess = undefined;
        // 	super.handleConnectionClosed();
        // }
        // protected createMessageTransports(encoding: string): Thenable<MessageTransports> {
        // 	function getEnvironment(env: any): any {
        // 		if (!env) {
        // 			return process.env;
        // 		}
        // 		let result: any = Object.create(null);
        // 		Object.keys(process.env).forEach(key => result[key] = process.env[key]);
        // 		Object.keys(env).forEach(key => result[key] = env[key]);
        // 		return result;
        // 	}
        // 	function startedInDebugMode(): boolean {
        // 		let args: string[] = (process as any).execArgv;
        // 		if (args) {
        // 			return args.some((arg) => /^--debug=?/.test(arg) || /^--debug-brk=?/.test(arg) || /^--inspect=?/.test(arg) || /^--inspect-brk=?/.test(arg));
        // 		};
        // 		return false;
        // 	}
        // 	let server = this._serverOptions;
        // 	// We got a function.
        // 	if (Is.func(server)) {
        // 		return server().then((result) => {
        // 			if (MessageTransports.is(result)) {
        // 				this._isDetached = !!result.detached;
        // 				return result;
        // 			} else if (StreamInfo.is(result)) {
        // 				this._isDetached = !!result.detached;
        // 				return { reader: new StreamMessageReader(result.reader), writer: new StreamMessageWriter(result.writer) };
        // 			} else {
        // 				let cp: ChildProcess;
        // 				if (ChildProcessInfo.is(result)) {
        // 					cp = result.process;
        // 					this._isDetached = result.detached;
        // 				} else {
        // 					cp = result;
        // 					this._isDetached = false;
        // 				}
        // 				cp.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 				return { reader: new StreamMessageReader(cp.stdout), writer: new StreamMessageWriter(cp.stdin) };
        // 			}
        // 		});
        // 	}
        // 	let json: NodeModule | Executable;
        // 	let runDebug = <{ run: any; debug: any; }>server;
        // 	if (runDebug.run || runDebug.debug) {
        // 		// We are under debugging. So use debug as well.
        // 		if (typeof v8debug === 'object' || this._forceDebug || startedInDebugMode()) {
        // 			json = runDebug.debug;
        // 		} else {
        // 			json = runDebug.run;
        // 		}
        // 	} else {
        // 		json = server as NodeModule | Executable;
        // 	}
        // 	return this._getServerWorkingDir(json.options).then(serverWorkingDir => {
        // 		if (NodeModule.is(json) && json.module) {
        // 			let node = json;
        // 			let transport = node.transport || TransportKind.stdio;
        // 			if (node.runtime) {
        // 				let args: string[] = [];
        // 				let options: ForkOptions = node.options || Object.create(null);
        // 				if (options.execArgv) {
        // 					options.execArgv.forEach(element => args.push(element));
        // 				}
        // 				args.push(node.module);
        // 				if (node.args) {
        // 					node.args.forEach(element => args.push(element));
        // 				}
        // 				let execOptions: ExecutableOptions = Object.create(null);
        // 				execOptions.cwd = serverWorkingDir;
        // 				execOptions.env = getEnvironment(options.env);
        // 				let pipeName: string | undefined = undefined;
        // 				if (transport === TransportKind.ipc) {
        // 					// exec options not correctly typed in lib
        // 					execOptions.stdio = <any>[null, null, null, 'ipc'];
        // 					args.push('--node-ipc');
        // 				} else if (transport === TransportKind.stdio) {
        // 					args.push('--stdio');
        // 				} else if (transport === TransportKind.pipe) {
        // 					pipeName = generateRandomPipeName();
        // 					args.push(`--pipe=${pipeName}`);
        // 				} else if (Transport.isSocket(transport)) {
        // 					args.push(`--socket=${transport.port}`);
        // 				}
        // 				args.push(`--clientProcessId=${process.pid.toString()}`);
        // 				if (transport === TransportKind.ipc || transport === TransportKind.stdio) {
        // 					let serverProcess = cp.spawn(node.runtime, args, execOptions);
        // 					if (!serverProcess || !serverProcess.pid) {
        // 						return Promise.reject<MessageTransports>(`Launching server using runtime ${node.runtime} failed.`);
        // 					}
        // 					this._serverProcess = serverProcess;
        // 					serverProcess.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 					if (transport === TransportKind.ipc) {
        // 						serverProcess.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 						return Promise.resolve({ reader: new IPCMessageReader(serverProcess), writer: new IPCMessageWriter(serverProcess) });
        // 					} else {
        // 						return Promise.resolve({ reader: new StreamMessageReader(serverProcess.stdout), writer: new StreamMessageWriter(serverProcess.stdin) });
        // 					}
        // 				} else if (transport == TransportKind.pipe) {
        // 					return createClientPipeTransport(pipeName!).then((transport) => {
        // 						let process = cp.spawn(node.runtime!, args, execOptions);
        // 						if (!process || !process.pid) {
        // 							return Promise.reject<MessageTransports>(`Launching server using runtime ${node.runtime} failed.`);
        // 						}
        // 						this._serverProcess = process;
        // 						process.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 						process.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 						return transport.onConnected().then((protocol) => {
        // 							return { reader: protocol[0], writer: protocol[1] };
        // 						});
        // 					})
        // 				} else if (Transport.isSocket(transport)) {
        // 					return createClientSocketTransport(transport.port).then((transport) => {
        // 						let process = cp.spawn(node.runtime!, args, execOptions);
        // 						if (!process || !process.pid) {
        // 							return Promise.reject<MessageTransports>(`Launching server using runtime ${node.runtime} failed.`);
        // 						}
        // 						this._serverProcess = process;
        // 						process.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 						process.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 						return transport.onConnected().then((protocol) => {
        // 							return { reader: protocol[0], writer: protocol[1] };
        // 						});
        // 					});
        // 				}
        // 			} else {
        // 				let pipeName: string | undefined = undefined;
        // 				return new Promise<MessageTransports>((resolve, reject) => {
        // 					let args = node.args && node.args.slice() || [];
        // 					if (transport === TransportKind.ipc) {
        // 						args.push('--node-ipc');
        // 					} else if (transport === TransportKind.stdio) {
        // 						args.push('--stdio');
        // 					} else if (transport === TransportKind.pipe) {
        // 						pipeName = generateRandomPipeName();
        // 						args.push(`--pipe=${pipeName}`);
        // 					} else if (Transport.isSocket(transport)) {
        // 						args.push(`--socket=${transport.port}`);
        // 					}
        // 					args.push(`--clientProcessId=${process.pid.toString()}`);
        // 					let options: ForkOptions = node.options || Object.create(null);
        // 					options.execArgv = options.execArgv || [];
        // 					options.cwd = serverWorkingDir;
        // 					if (transport === TransportKind.ipc || transport === TransportKind.stdio) {
        // 						electron.fork(node.module, args || [], options, (error, serverProcess) => {
        // 							if (error || !serverProcess) {
        // 								reject(error);
        // 							} else {
        // 								this._serverProcess = serverProcess;
        // 								serverProcess.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 								if (transport === TransportKind.ipc) {
        // 									serverProcess.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 									resolve({ reader: new IPCMessageReader(this._serverProcess), writer: new IPCMessageWriter(this._serverProcess) });
        // 								} else {
        // 									resolve({ reader: new StreamMessageReader(serverProcess.stdout), writer: new StreamMessageWriter(serverProcess.stdin) });
        // 								}
        // 							}
        // 						});
        // 					} else if (transport === TransportKind.pipe) {
        // 						createClientPipeTransport(pipeName!).then((transport) => {
        // 							electron.fork(node.module, args || [], options, (error, cp) => {
        // 								if (error || !cp) {
        // 									reject(error);
        // 								} else {
        // 									this._serverProcess = cp;
        // 									cp.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 									cp.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 									transport.onConnected().then((protocol) => {
        // 										resolve({ reader: protocol[0], writer: protocol[1] });
        // 									});
        // 								}
        // 							});
        // 						});
        // 					} else if (Transport.isSocket(transport)) {
        // 						createClientSocketTransport(transport.port).then((transport) => {
        // 							electron.fork(node.module, args || [], options, (error, cp) => {
        // 								if (error || !cp) {
        // 									reject(error);
        // 								} else {
        // 									this._serverProcess = cp;
        // 									cp.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 									cp.stdout.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 									transport.onConnected().then((protocol) => {
        // 										resolve({ reader: protocol[0], writer: protocol[1] });
        // 									});
        // 								}
        // 							});
        // 						});
        // 					}
        // 				});
        // 			}
        // 		} else if (Executable.is(json) && json.command) {
        // 			let command: Executable = <Executable>json;
        // 			let args = command.args || [];
        // 			let options = command.options || Object.create(null);
        // 			options.cwd = serverWorkingDir;
        // 			let serverProcess = cp.spawn(command.command, args, options);
        // 			if (!serverProcess || !serverProcess.pid) {
        // 				return Promise.reject<MessageTransports>(`Launching server using command ${command.command} failed.`);
        // 			}
        // 			serverProcess.stderr.on('data', data => this.outputChannel.append(Is.string(data) ? data : data.toString(encoding)));
        // 			this._serverProcess = serverProcess;
        // 			this._isDetached = !!options.detached;
        // 			return Promise.resolve({ reader: new StreamMessageReader(serverProcess.stdout), writer: new StreamMessageWriter(serverProcess.stdin) });
        // 		}
        // 		return Promise.reject<MessageTransports>(new Error(`Unsupported server configuration ` + JSON.stringify(server, null, 4)));
        // 	});
        // }
        registerProposedFeatures() {
            this.registerFeatures(ProposedFeatures.createAll(this));
        }
        registerBuiltinFeatures() {
            super.registerBuiltinFeatures();
            this.registerFeature(new configuration_1.ConfigurationFeature(this));
            this.registerFeature(new typeDefinition_1.TypeDefinitionFeature(this));
            this.registerFeature(new implementation_1.ImplementationFeature(this));
            this.registerFeature(new colorProvider_1.ColorProviderFeature(this));
            this.registerFeature(new workspaceFolders_1.WorkspaceFoldersFeature(this));
        }
    }
    exports.LanguageClient = LanguageClient;
    // export class SettingMonitor {
    // 	private _listeners: any[];
    // 	constructor(private _client: LanguageClient, private _setting: string) {
    // 		this._listeners = [];
    // 	}
    // 	public start(): any {
    // 		vscode.Workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this._listeners);
    // 		this.onDidChangeConfiguration();
    // 		return new vscode.Disposable(() => {
    // 		});
    // 	}
    // 	private onDidChangeConfiguration(): void {
    // 		let index = this._setting.indexOf('.');
    // 		let primary = index >= 0 ? this._setting.substr(0, index) : this._setting;
    // 		let rest = index >= 0 ? this._setting.substr(index + 1) : undefined;
    // 		let enabled = rest ? vscode.Workspace.getConfiguration(primary).get(rest, false) : Workspace.getConfiguration(primary);
    // 		if (enabled && this._client.needsStart()) {
    // 			this._client.start();
    // 		} else if (!enabled && this._client.needsStop()) {
    // 			this._client.stop();
    // 		}
    // 	}
    // }
    // Exporting proposed protocol.
    var ProposedFeatures;
    (function (ProposedFeatures) {
        function createAll(_client) {
            let result = [];
            return result;
        }
        ProposedFeatures.createAll = createAll;
    })(ProposedFeatures = exports.ProposedFeatures || (exports.ProposedFeatures = {}));
});
